package com.xucy.springboot.annotationaop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

/**
 * @Author xucy
 * @Date 2019-08-01 14:27
 * @Description
 **/
@Aspect
@Component
public class AspectAop {

    /**
     * ThreadLocal保证不受其他线程影响，用于记录接口响应时间
     *
     * @Author xucy
     * @Date 14:33 2019-08-01
     * @param
     * @return
     */
    private static ThreadLocal<Long> threadLocal = new ThreadLocal<Long>();

    @Pointcut("execution(public * com.xucy.springboot.annotationaop..*.*(..))")
    public void pointCut(){

    }


    /**
     *
     *
     * @Author xucy
     * @Date 14:30 2019-08-01
     * @param joinPoint 连接点
     * @return
     */
    @Before(value = "pointCut()")
    public void beforeMethod(JoinPoint joinPoint){
        //记录请求接口开始时间
        threadLocal.set(System.currentTimeMillis());
    }



    @After(value = "pointCut()")
    public void afterMethod(JoinPoint joinPoint) throws NoSuchFieldException, IllegalAccessException {

        MethodSignature methodSignature= (MethodSignature) joinPoint.getSignature();

        // 请求的方法名
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = methodSignature.getName();
        Method method=methodSignature.getMethod();
        Parameter[] parameters= method.getParameters();
        for(Parameter parameter:parameters){
        }

        // 请求的方法参数值
        Object[] args = joinPoint.getArgs();
        String id="";
        if(args.length>0){
          Object object=args[0];
              Field[] fields=args[0].getClass().getDeclaredFields();

              for(Field field:fields){
                  if(field.isAnnotationPresent(LogNo.class)){
                      id=field.get(object)+"";
                  }
              }
        }
        LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
        String[] paramNames = u.getParameterNames(method);
        String params = "";
        if (args != null && paramNames != null) {
            for (int i = 0; i < args.length; i++) {
                params += "  " + paramNames[i] + ": " + args[i];
            }
        }
        StringBuffer log = new StringBuffer();
        log.append("=======")
                .append("请求的方法:").append(className).append(".").append(methodName).append("=====")
                .append("请求参数:").append(params);
        System.out.println(log);

        if(method.isAnnotationPresent(LogAnnotation.class)){
                LogAnnotation logAnnotation=method.getAnnotation(LogAnnotation.class);
                System.out.println(logAnnotation.operatorName());
                System.out.println(logAnnotation.operatorNo().length()==0?id:logAnnotation.operatorNo());
                System.out.println(logAnnotation.operatorTime());
                System.out.println(logAnnotation.operatorUser());
        }else{
            System.out.println("没有日志注解");
        }

        Long startTime=threadLocal.get();
        Long endTime=System.currentTimeMillis();

        System.out.println("方法调用共花费时间"+(endTime-startTime));
    }
}
